﻿/*
 * Author: Brian Brewder
 * Website: http://redwerb.com
 */

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
using System.IO;
using My = Redwerb.Visualizers.Properties;
using System.Diagnostics;

namespace Redwerb.Visualizers.ImageVisualizer
{
    public partial class ImageVisualizerDialog : Form
    {

        #region Initialization and Destruction

        public ImageVisualizerDialog()
        {
            InitializeComponent();
            rdoLight.Checked = true;
        }

        #endregion

        #region Fields and Properties

        private const int cMinPct = 10;
        private const int cMaxPct = 300;

        public Image Image
        {
            get { return imgFrame.Image; }
            set
            {
                imgFrame.Image = value;
                lblHeight.Text = value.Height.ToString();
                lblWidth.Text = value.Width.ToString();
                lblType.Text = GetExtension(value);
                lblHRes.Text = value.HorizontalResolution.ToString();
                lblVRes.Text = value.VerticalResolution.ToString();
                var imgSz = SizeOf(value);
                lblSize.Text = "~" + ToMemSize(imgSz);
                toolTip1.SetToolTip(lblSize, string.Format("{0} bytes", imgSz));
            }
        }

        #endregion

        #region Methods

        public static string ToMemSize(long numBytes)
        {
            if (numBytes < 1000)
                return string.Format("{0} bytes", numBytes);
            if (numBytes < 1000000)
                return string.Format("{0:0.0} KB", (double)numBytes / 1000);
            else
                return string.Format("{0:0.0} MB", (double)numBytes / 1000000);
        }

        public static long SizeOf(Image img)
        {
            //var sz = img.Height * img.Width;
            //return sz*4;
            var imgBytes = ToBytes(img);
            return imgBytes.LongLength;
        }

        private static byte[] ToBytes(System.Drawing.Image img)
        {
            using (MemoryStream ms = new MemoryStream())
            {
                img.Save(ms, img.RawFormat);
                return ms.ToArray();
            }
        }

        public static string GetExtension(Image img)
        {
            if (ImageFormat.Jpeg.Equals(img.RawFormat))
                return "jpg";
            else if (ImageFormat.Gif.Equals(img.RawFormat))
                return "gif";
            else if (ImageFormat.Bmp.Equals(img.RawFormat))
                return "bmp";
            else if (ImageFormat.Emf.Equals(img.RawFormat))
                return "emf";
            else if (ImageFormat.Exif.Equals(img.RawFormat))
                return "exif";
            else if (ImageFormat.Icon.Equals(img.RawFormat))
                return "ico";
            else if (ImageFormat.Png.Equals(img.RawFormat))
                return "png";
            else if (ImageFormat.Tiff.Equals(img.RawFormat))
                return "tif";
            else if (ImageFormat.Wmf.Equals(img.RawFormat))
                return "wmf";
            else
                return "n/a";
        }

        private void UpdateFrameBackground()
        {
            if (rdoDark.Checked)
            {
                imgFrame.BackgroundImage = My.Resources.PolkaDots_Dark;
                imgFrame.ImageBorderColor = Color.White;
            }
            else
            {
                imgFrame.BackgroundImage = My.Resources.PolkaDots_Light;
                imgFrame.ImageBorderColor = Color.Black;
            }
        }

        private void SetPictureBoxSize(int pct)
        {
            sldScale.SetValue(pct, cMinPct, cMaxPct);
        }

        private void ScrollImage(ScrollDir dir)
        {
            var pt = imgFrame.ImageLocation;

            if ((dir & ScrollDir.Left) == ScrollDir.Left)
                pt.X -= 10;
            if ((dir & ScrollDir.Right) == ScrollDir.Right)
                pt.X += 10;
            if ((dir & ScrollDir.Up) == ScrollDir.Up)
                pt.Y -= 10;
            if ((dir & ScrollDir.Down) == ScrollDir.Down)
                pt.Y += 10;

            imgFrame.ImageLocation = pt;
        }

        #endregion

        #region Event Handlers

        private void btnClose_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void Background_CheckedChanged(object sender, EventArgs e)
        {
            UpdateFrameBackground();
        }

        private void mnuCopyImage_Click(object sender, EventArgs e)
        {
            Clipboard.SetImage(this.Image);
        }

        private void mnuSaveImage_Click(object sender, EventArgs e)
        {
            var ext = GetExtension(this.Image);
            dlgSaveImage.DefaultExt = ext;
            dlgSaveImage.Filter = string.Format("{0}|*.{0}|All Images|*.jpg;*.gif;*.bmp;*.emf;*.exif;*.ico;*.png;*.tif;*.wmf|All Files|*.*", ext);
            if (dlgSaveImage.ShowDialog(this) != DialogResult.OK) return;
            this.Image.Save(dlgSaveImage.FileName);
        }

        private void ImageVisualizerDialog_KeyDown(object sender, KeyEventArgs e)
        {
            switch (e.KeyCode)
            {
                case Keys.F1:
                    btnShortcuts.PerformClick();
                    e.Handled = true;
                    break;
                case Keys.F11:
                    switch (this.WindowState)
                    {
                        case FormWindowState.Normal:
                            this.WindowState = FormWindowState.Maximized;
                            break;
                        default:
                            this.WindowState = FormWindowState.Normal;
                            break;
                    }
                    e.Handled = true;
                    break;
                case Keys.Space:
                    chkBorder.Checked = !chkBorder.Checked;
                    e.Handled = true;
                    break;
                case Keys.Add:
                    var aval = sldScale.GetValue(cMinPct, cMaxPct);
                    if (aval < cMaxPct)
                        SetPictureBoxSize(aval + 25);
                    e.Handled = true;
                    break;
                case Keys.Subtract:
                    var sval = sldScale.GetValue(cMinPct, cMaxPct);
                    if (sval > cMinPct)
                        SetPictureBoxSize(sval - 25);
                    e.Handled = true;
                    break;
                case Keys.NumPad0:
                case Keys.D0:
                    SetPictureBoxSize(100);
                    e.Handled = true;
                    break;
                case Keys.Decimal:
                    btnBestFit.PerformClick();
                    e.Handled = true;
                    break;
                case Keys.Home:
                case Keys.NumPad5:
                    imgFrame.CenterImage(.5f, .5f);
                    break;
                case Keys.S:
                    if (e.Control)
                    {
                        mnuSaveImage.PerformClick();
                        e.Handled = true;
                    }
                    break;
                case Keys.C:
                    if (e.Control)
                    {
                        mnuCopyImage.PerformClick();
                        e.Handled = true;
                    }
                    break;
                case Keys.NumPad1:
                    ScrollImage(ScrollDir.Down | ScrollDir.Left);
                    e.Handled = true;
                    break;
                case Keys.NumPad2:
                    ScrollImage(ScrollDir.Down);
                    e.Handled = true;
                    break;
                case Keys.NumPad3:
                    ScrollImage(ScrollDir.Down | ScrollDir.Right);
                    e.Handled = true;
                    break;
                case Keys.NumPad4:
                    ScrollImage(ScrollDir.Left);
                    e.Handled = true;
                    break;
                case Keys.NumPad6:
                    ScrollImage(ScrollDir.Right);
                    e.Handled = true;
                    break;
                case Keys.NumPad7:
                    ScrollImage(ScrollDir.Up | ScrollDir.Left);
                    e.Handled = true;
                    break;
                case Keys.NumPad8:
                    ScrollImage(ScrollDir.Up);
                    e.Handled = true;
                    break;
                case Keys.NumPad9:
                    ScrollImage(ScrollDir.Up | ScrollDir.Right);
                    e.Handled = true;
                    break;
            }
        }

        protected override bool ProcessDialogKey(Keys keyData)
        {
            switch (keyData)
            {
                case Keys.Tab:
                    if (rdoDark.Checked)
                        rdoLight.Checked = true;
                    else
                        rdoDark.Checked = true;
                    return false;
                case Keys.Left:
                    ScrollImage(ScrollDir.Left);
                    return false;
                case Keys.Right:
                    ScrollImage(ScrollDir.Right);
                    return false;
                case Keys.Up:
                    ScrollImage(ScrollDir.Up);
                    return false;
                case Keys.Down:
                    ScrollImage(ScrollDir.Down);
                    return false;
                default:
                    return base.ProcessDialogKey(keyData);
            }
        }

        private void ImageVisualizerDialog_Load(object sender, EventArgs e)
        {
            sldScale.AddStopValue(10, 10, 300);
            sldScale.AddStopValue(50, 10, 300);
            sldScale.AddStopValue(100, 10, 300);
            sldScale.AddStopValue(150, 10, 300);
            sldScale.AddStopValue(200, 10, 300);
            sldScale.AddStopValue(250, 10, 300);
            sldScale.AddStopValue(300, 10, 300);
            btnBestFit.PerformClick();
        }

        private void btn100_Click(object sender, EventArgs e)
        {
            SetPictureBoxSize(100);
        }

        private void btnBestFit_Click(object sender, EventArgs e)
        {
            sldScale.SetValue(imgFrame.GetBestFit(), (float)cMinPct / 100, (float)cMaxPct / 100);
            imgFrame.CenterImage(.5f, .5f);
        }

        private void btnShortcuts_Click(object sender, EventArgs e)
        {
            var dlg = new ImageVisualizerShortcutsDialog();
            dlg.ShowDialog(this);
        }

        private void lnkRedwerb_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            Process.Start("http://redwerb.com");
        }

        private void chkBorder_CheckedChanged(object sender, EventArgs e)
        {
            imgFrame.ImageBorder = chkBorder.Checked;
        }

        private void sldScale_ValueChanged(object sender, EventArgs e)
        {
            imgFrame.ImageScale = sldScale.GetValue(.1f, 3f);
        }

        private void imgFrame_ImageScaleChanged(object sender, EventArgs e)
        {
            lblZoom.Text = string.Format("{0:P0}", imgFrame.ImageScale);
            //sldScale.SetValue(
        }

        #endregion

        [Flags]
        private enum ScrollDir
        {
            Right = 1,
            Left = 2,
            Up = 4,
            Down = 8
        }

    }
}
